﻿using PaddleOCRSharp;
using System.Drawing;
using System.Drawing.Imaging;
using static System.Formats.Asn1.AsnWriter;

namespace ImageProcess
{
    public class OcrHelper : IDisposable
    {
        OCRModelConfig _config;
        OCRParameter _parameter;
        PaddleOCREngine _engine;
        private bool disposedValue;

        public float Threshold { get; set; } = 0.618f;

        public OcrHelper()
        {
            string modelPathroot = AppDomain.CurrentDomain.BaseDirectory + @"\inference";
            _config = new OCRModelConfig
            {
                det_infer = modelPathroot + @"\ch_PP-OCRv4_det_infer",
                cls_infer = modelPathroot + @"\ch_ppocr_mobile_v2.0_cls_infer",
                rec_infer = modelPathroot + @"\ch_PP-OCRv4_rec_infer",
                keys = modelPathroot + @"\ppocr_keys.txt"
            };

            _parameter = new OCRParameter()
            {
                cpu_math_library_num_threads = 10,//预测并发线程数
                enable_mkldnn = true,
                cls = false, //是否执行文字方向分类；默认false
                det = true,//是否开启文本框检测，用于检测文本块
                use_angle_cls = false,//是否开启方向检测，用于检测识别180旋转
                det_db_score_mode = true,//是否使用多段线，即文字区域是用多段线还是用矩形，
                max_side_len = 960,
                rec_img_h = 48,
                rec_img_w = 320,
                det_db_thresh = 0.3f,
                det_db_box_thresh = Threshold
            };

            //初始化OCR引擎
            _engine = new PaddleOCREngine(_config, _parameter);
        }

        /// <summary>
        /// 获取文本列表
        /// </summary>
        /// <param name="imagefile"></param>
        /// <returns></returns>
        public List<string> GetTextList(string imagefile)
        {
            OCRResult result = _engine.DetectText(imagefile);
            List<string> texts = [];
            for (int i = 0; i < result.TextBlocks.Count; i++)
            {
                texts.Add(result.TextBlocks[i].Text);
            }
            return texts;
        }

        /// <summary>
        /// 获取文本列表
        /// </summary>
        /// <param name="imagebyte"></param>
        /// <returns></returns>
        public List<string> GetTextList(byte[] imagebyte)
        {
            OCRResult result = _engine.DetectText(imagebyte);
            List<string> texts = [];
            for (int i = 0; i < result.TextBlocks.Count; i++)
            {
                texts.Add(result.TextBlocks[i].Text);
            }
            return texts;
        }

        /// <summary>
        /// 获取文本列表
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public List<string> GetTextList(Image image)
        {
            using MemoryStream memoryStream = new();
            // 保存图片到内存流
#pragma warning disable CA1416 // 验证平台兼容性
            image.Save(memoryStream, ImageFormat.Png);
#pragma warning restore CA1416 // 验证平台兼容性
            // 获取字节数组
            byte[] bytes = memoryStream.ToArray();
            OCRResult result = _engine.DetectText(bytes);
            List<string> texts = [];
            for (int i = 0; i < result.TextBlocks.Count; i++)
            {
                texts.Add(result.TextBlocks[i].Text);
            }
            return texts;
        }

        /// <summary>
        /// 获取文本
        /// </summary>
        /// <param name="imagefile"></param>
        /// <returns></returns>
        public string GetText(string imagefile)
        {
            try
            {
                OCRResult result = _engine.DetectText(imagefile);
                return result.Text;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        public string GetText(string imagefile, out float score)
        {
            try
            {
                OCRResult result = _engine.DetectText(imagefile);
                List<float> scores = [];
                foreach (var tmp in result.TextBlocks)
                {
                    scores.Add(tmp.Score);
                }
                score = scores.Sum() / scores.Count;
                return result.Text;
            }
            catch (Exception)
            {
                score = 0;
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取文本
        /// </summary>
        /// <param name="imagebyte"></param>
        /// <returns></returns>
        public string GetText(byte[] imagebyte)
        {
            OCRResult result = _engine.DetectText(imagebyte);
            return result.Text;
        }

        /// <summary>
        /// 获取文本
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public string GetText(Image image)
        {
            using MemoryStream memoryStream = new();
            // 保存图片到内存流
#pragma warning disable CA1416 // 验证平台兼容性
            image.Save(memoryStream, ImageFormat.Png);
#pragma warning restore CA1416 // 验证平台兼容性
            // 获取字节数组
            byte[] bytes = memoryStream.ToArray();
            OCRResult result = _engine.DetectText(bytes);
            return result.Text;
        }

        #region 销毁
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                }
                _engine.Dispose();
                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
                // TODO: 将大型字段设置为 null
                disposedValue = true;
            }
        }

        // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        // ~OcrHelper()
        // {
        //     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
        //     Dispose(disposing: false);
        // }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}
